﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.IO;
using System.IO.Packaging;
using System.Xml;
using System.Xml.Schema;

namespace Songhay.OpenXml
{
    /// <summary>
    /// Static members for Open XML.
    /// </summary>
    public static partial class OpenXmlUtility
    {
        /// <summary>
        /// Gets the contents as XML.
        /// </summary>
        /// <param name="part">The part.</param>
        public static XElement GetPartContentsAsXml(PackagePart part)
        {
            if(part.ContentType.EndsWith("xml"))
            {
                using(Stream str = part.GetStream())
                using(StreamReader streamReader = new StreamReader(str))
                using(XmlReader xr = XmlReader.Create(streamReader))
                    return new XElement(NamespaceXmlPackage + "part",
                        new XAttribute(NamespaceXmlPackage + "name", part.Uri),
                        new XAttribute(NamespaceXmlPackage + "contentType", part.ContentType),
                        new XElement(NamespaceXmlPackage + "xmlData",
                            XElement.Load(xr)
                        )
                    );
            }
            else
            {
                using(Stream str = part.GetStream())
                using(BinaryReader binaryReader = new BinaryReader(str))
                {
                    int len = (int)binaryReader.BaseStream.Length;
                    byte[] byteArray = binaryReader.ReadBytes(len);
                    // the following expression creates the base64String, then chunks
                    // it to lines of 76 characters long
                    string base64String = (System.Convert.ToBase64String(byteArray))
                        .Select
                        (
                            (c, i) => new
                            {
                                Character = c,
                                Chunk = i / 76
                            }
                        )
                        .GroupBy(c => c.Chunk)
                        .Aggregate(
                            new StringBuilder(),
                            (s, i) =>
                                s.Append(
                                    i.Aggregate(
                                        new StringBuilder(),
                                        (seed, it) => seed.Append(it.Character),
                                        sb => sb.ToString()
                                    )
                                )
                                .Append(Environment.NewLine),
                            s => s.ToString()
                        );
                    return new XElement(NamespaceXmlPackage + "part",
                        new XAttribute(NamespaceXmlPackage + "name", part.Uri),
                        new XAttribute(NamespaceXmlPackage + "contentType", part.ContentType),
                        new XAttribute(NamespaceXmlPackage + "compression", "store"),
                        new XElement(NamespaceXmlPackage + "binaryData", base64String)
                    );
                }
            }
        }
    }
}
